use argparse::{ArgumentParser, Store};
use ycspice::preprocess::expand_subckt;
use ycspice::netlist::Netlist;
use ycspice::simulate::Simulator;
use ycspice::draw::Drawer;

#[derive(Default)]
struct Options {
    spice_file_path: String,
    sim_time: f64,
    delta_time: f64,
    output_foler_path: String,
    drawer: Drawer,
}

fn parse_options() -> Options {
    let mut options = Options::default();
    options.output_foler_path = "./pic".to_string();

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("ycspice");
        ap.refer(&mut options.spice_file_path).required()
            .add_argument("input_file_path", Store, "Input spice file path");
        ap.refer(&mut options.sim_time).required()
            .add_argument("sim_time", Store, "Simulate time");
        ap.refer(&mut options.delta_time).required()
            .add_argument("delta_time", Store, "Simulate delta time");
        ap.refer(&mut options.output_foler_path)
            .add_option(&["-o", "--output"], Store, "Ouput folder");
        ap.refer(&mut options.drawer)   
            .add_option(&["-d", "--drawe_strategy"], Store, r#"Drawer to run (either "mul_page" or "one_page")"#);
        ap.parse_args_or_exit();
    }

    options
}

fn result_main() -> Result<(), String> {
    let options  = parse_options();
    let expanded_path = expand_subckt(&options.spice_file_path)
        .ok_or("Expand failed".to_string())?;

    let netlist = Netlist::load_from_file(expanded_path)?;
    let simulator = Simulator::load_netlist(netlist)?;

    let results = simulator.simulate(options.sim_time, options.delta_time)?;

    options.drawer.draw_results(
        &results, 
        options.sim_time, 
        options.delta_time, 
        &options.output_foler_path)?;

    Ok(())
}

// simulate <spice file> <sim time> <delta time>
fn main() {
    match result_main() {
        Ok(()) => {},
        Err(err) => println!("Error: {:?}", err),
    }
}   
